package civicinity.ist.psu.edu.utils;

import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;

public class MyLocation {
	private Timer mTimer;
	private LocationManager mLocManager;
	private LocationResult mLocResult;
	private boolean mGPSEnabled = false;
	private boolean mNetworkEnabled = false;
	
	public boolean getLocation(Context context, LocationResult result) {
		mLocResult = result;
		
		if(mLocManager == null) {
			mLocManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
		}
		
		try {
			mGPSEnabled = mLocManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
			mNetworkEnabled = mLocManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
		}
		catch(Exception e) {
			
		}
		
		if(!mGPSEnabled && !mNetworkEnabled) {
			return false;
		}
		
		if(mGPSEnabled) {
			mLocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mGPSListener);
		}
		if(mNetworkEnabled) {
			mLocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mNetworkListener);
		}
		
		mTimer = new Timer();
		mTimer.schedule(new GetLastLocation(), 20 * 1000);
		
		return true;
	}
	
	LocationListener mGPSListener = new LocationListener() {

		@Override
		public void onLocationChanged(Location location) {
			// TODO Auto-generated method stub
			if(location.getAccuracy() < 30) {
				mTimer.cancel();
				mLocResult.gotLocation(location);
				mLocManager.removeUpdates(this);
				mLocManager.removeUpdates(mGPSListener);
			}
		}

		@Override
		public void onProviderDisabled(String provider) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void onProviderEnabled(String provider) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			// TODO Auto-generated method stub
			
		}
		
	};
	
	LocationListener mNetworkListener = new LocationListener() {

		@Override
		public void onLocationChanged(Location location) {
			// TODO Auto-generated method stub
			if(location.getAccuracy() < 30) {
				mTimer.cancel();
				mLocResult.gotLocation(location);
				mLocManager.removeUpdates(this);
				mLocManager.removeUpdates(mNetworkListener);
			}
		}

		@Override
		public void onProviderDisabled(String provider) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void onProviderEnabled(String provider) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			// TODO Auto-generated method stub
			
		}
		
	};
	
	class GetLastLocation extends TimerTask {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			Log.i("K", "Fail to get the accurate results. Use the lastknown GPS data.");
			
			mLocManager.removeUpdates(mGPSListener);
			mLocManager.removeUpdates(mNetworkListener);
			
			Location netLoc = null;
			Location gpsLoc	= null;
			
			if(mGPSEnabled) {
				gpsLoc = mLocManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
			}
			
			if(mNetworkEnabled) {
				netLoc = mLocManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
			}
			
			if(gpsLoc != null && netLoc != null) {
				if(gpsLoc.getTime() > netLoc.getTime()) {
					mLocResult.gotLocation(gpsLoc);
				}
				else {
					mLocResult.gotLocation(netLoc);
				}
				return;
			}
			
			if(gpsLoc != null) {
				mLocResult.gotLocation(gpsLoc);
				return;
			}
			if(netLoc != null) {
				mLocResult.gotLocation(netLoc);
				return;
			}
			
			mLocResult.gotLocation(null);
			
		}
		
	}
	
	public static abstract class LocationResult {
		public abstract void gotLocation(Location location);
	}
}
